package com.seleniti.enpareja.web.desktop.client.ui.view;

import org.ioc.commons.impl.gwt.client.ui.HasEnabledWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasLoaderWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasValueWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasVisibilityWrapper;
import org.ioc.commons.impl.gwt.client.ui.ViewComposite;
import org.ioc.commons.impl.gwt.shared.common.util.WrappedDeckPanelAsEnum;
import org.ioc.commons.ui.HasEnabled;
import org.ioc.commons.ui.HasLoader;
import org.ioc.commons.ui.HasValue;
import org.ioc.commons.ui.HasVisibility;
import org.ioc.commons.ui.features.Info;
import org.ioc.commons.ui.impl.HasEnabledAdapter;
import org.ioc.commons.ui.impl.HasValueAdapter;
import org.ioc.commons.ui.impl.OnChangeCommand;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.TableElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.Html5FormPanel;
import com.google.gwt.user.client.ui.Html5PasswordBox;
import com.google.gwt.user.client.ui.Html5TextBox;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.Widget;
import com.seleniti.enpareja.controller.control.place.EnParejaPlace;
import com.seleniti.enpareja.controller.ui.view.LoginView;
import com.seleniti.enpareja.controller.ui.view.LoginView.Action;
import com.seleniti.enpareja.controller.ui.view.LoginView.Event;
import com.seleniti.enpareja.controller.ui.view.LoginView.Operation;
import com.seleniti.enpareja.controller.ui.view.LoginView.Presenter;
import com.seleniti.enpareja.controller.ui.view.LoginViewPresenter;
import com.seleniti.enpareja.web.desktop.client.ui.widget.InfoInlineWidget;

public class LoginViewWidget extends EnParejaBaseView<Event, Operation, Action, Presenter> implements LoginView {

	private static LoginWidgetUiBinder uiBinder = GWT.create(LoginWidgetUiBinder.class);

	interface LoginWidgetUiBinder extends UiBinder<Widget, LoginViewWidget> {
	}

	@UiField
	TableElement loginBox;

	@UiField
	Html5TextBox loginName;

	@UiField
	Html5PasswordBox loginPassword;

	@UiField
	CheckBox rememberMe;

	@UiField
	InfoInlineWidget loginFailed;

	@UiField
	DivElement loader;

	@UiField
	PushButton btnLogin;

	@UiField
	Html5FormPanel form;

	@UiField
	DeckPanel mainPanel;
	
	@UiField 
	Button btnDownloadApp;
	
	@UiField
	Button btnSolveNoPasswordSet;

	private WrappedDeckPanelAsEnum<Board> board;

	private EnParejaPlace goToPlaceWhenOk;

	public LoginViewWidget() {
		super();
		this.presenter = new LoginViewPresenter(this, eventbus, operationManager, actionController);
		initWidget(uiBinder.createAndBindUi(this));
		this.board = new WrappedDeckPanelAsEnum<Board>(mainPanel, Board.values());
	}

	@Override
	public void activate() {
		super.activate();

		Scheduler.get().scheduleDeferred(new ScheduledCommand() {

			@Override
			public void execute() {
				loginName.setFocus(true);
			}
		});
	}

	@Override
	public HasValue<String> loginName() {
		return HasValueWrapper.from(this.loginName, true, this);
	}

	@Override
	public HasValue<String> loginPassword() {
		return HasValueWrapper.from(this.loginPassword, true, this);
	}

	@Override
	public HasValue<Boolean> rememberMe() {
		return HasValueWrapper.from(this.rememberMe, true, this);
	}

	@Override
	public Info loginFailed() {
		return this.loginFailed;
	}
	
	@Override
	public void focusLoginFailed() {
		Scheduler.get().scheduleFinally(new ScheduledCommand() {

			@Override
			public void execute() {
				loginFailed.getElement().scrollIntoView();
			}
		});
	}

	@UiHandler("loginName")
	void onLoginNameKeyPressed(KeyPressEvent evt) {
		if (this.enterPressed(evt)) {
			loginPassword.setFocus(true);
		}
	}

	@UiHandler("loginPassword")
	void onLoginPasswordKeyPressed(KeyPressEvent evt) {
		if (this.enterPressed(evt)) {
			tryLogin();
		}
	}

	@UiHandler("btnLogin")
	void onLoginButtonClicked(ClickEvent evt) {
		this.tryLogin();
	}

	@UiHandler("btnSolveNoPasswordSet")
	void onSolveNoPasswordSetButtonClicked(ClickEvent evt) {
		this.presenter.onGoToSolveNoPasswordSetView();
	}

	@UiHandler("btnCloseErrorBox")
	void onCloseErrorBoxButtonClicked(ClickEvent evt) {
		this.loginFailed().setVisible(false);
	}

	@UiHandler("btnGoogleLogin")
	void onGoogleLoginClicked(ClickEvent evt) {
		this.goToGoogleLoginView();
	}

	@UiHandler("btnAndroidLogin")
	void onAndroidLoginClicked(ClickEvent evt) {
		this.goToGoogleLoginView();
	}
	@UiHandler("btnDownloadApp")
	void onDownloadAppClicked(ClickEvent evt) {
		this.goToDownloadAppView();
	}
	
	@Override
	public HasVisibility downloadAppButtonVisibility() {
		return HasVisibilityWrapper.from(btnDownloadApp, this);
	}
	
	@Override
	public void goToDownloadAppView() {
		this.presenter.onGoToDownloadAppView();
	}

	@UiHandler("btnGoStandardLogin")
	void onGoStandardLoginClicked(ClickEvent evt) {
		this.board().setValue(Board.STANDARD_LOGIN);
	}

	@Override
	public void goToGoogleLoginView() {
		this.presenter.onGoToGoogleLoginView();
	}

	@UiHandler("btnSignUp")
	void onSignUpButtonClicked(ClickEvent evt) {
		this.goToSignUpView();
	}

	@Override
	public void goToSignUpView() {
		this.presenter.onGoToSignUpView();
	}

	@Override
	public void tryLogin() {
		if (form.checkValidity()) {
			this.presenter.onTryLogin();
		}
	}

	@Override
	public HasLoader tryingLogin() {
		return HasLoaderWrapper.fromVisible(loader, this);
	}

	@Override
	public HasEnabled actionsEnabled() {
		return HasEnabledAdapter.forField("actionsEnabled", this, true).onChange(new OnChangeCommand<Boolean>() {

			@Override
			public void execute(Boolean enabled) {
				HasEnabledWrapper.setEnabled(enabled, btnLogin);
			}
		});
	}

	@Override
	protected void onUnload() {
		super.onUnload();
		HasValueAdapter.cleanAdapters(this);
	}

	@Override
	public HasValue<Board> board() {
		return this.board;
	}

	@Override
	public void setGoToPlaceWhenOk(EnParejaPlace goWhenOk) {
		this.goToPlaceWhenOk = goWhenOk;
	}

	@Override
	public EnParejaPlace getGoToPlaceWhenOk() {
		return this.goToPlaceWhenOk;
	}
	
	@Override
	public HasVisibility infoSolveNoPasswordSet() {
		return HasVisibilityWrapper.from(btnSolveNoPasswordSet, this);
	}
}
